//
// Created by xu on 2024/11/19.
//
#include <stdio.h>
#include <stdint.h>
#include <libavutil/avutil.h>
#include <sys/stat.h>


#define AUDIO_FORMAT_PCM 1
#define AUDIO_FORMAT_FLOAT 3

// wav文件头（44字节）
typedef struct {
    // RIFF chunk的ID
    uint8_t riffChunkId[4];
    // RIFF chunk的data大小，即文件总长度减去8字节
    uint32_t riffChunkDataSize;
    // "WAVE"
    uint8_t format[4];
    // fmt chunk id
    uint8_t fmtChunkId[4];
    // fmt chunk data的大小：存储pcm数据时是16
    uint32_t fmtChunkDataSize;
    // 音频编码：1表示pcm 3表示floating point
    uint16_t audioFormat;
    // 声道数
    uint16_t numChannels;
    // 采样率
    uint32_t sampleRate;
    // 字节率 = sampleRate * blockAlign
    uint32_t byteRate;
    // 一个样本的字节数 = bitsPerSample * numChannels >> 3
    uint16_t blockAlign;
    // 位深度
    uint16_t bitsPerSample;
    // data chunk id
    uint8_t dataChunkId[4];
    // data chunk的data大小：音频数据的总长度，即文件总长度减去文件头的长度（一般是44）
    uint32_t dataChunkDataSize;
} WAVHeader;


void pcm2wav(WAVHeader *header, const char *pcmFilename, const char *wavFilename) {
    header->blockAlign = header->bitsPerSample * header->numChannels >> 3;
    header->byteRate = header->sampleRate * header->blockAlign;
    // 打开pcm文件
    FILE *pcmFile = fopen(pcmFilename, "rb");
    if (pcmFile == NULL) {
        av_log(NULL, AV_LOG_INFO, "文件打开失败：%s\n", pcmFilename);
        return;
    }

    struct stat st;
    if (stat(pcmFilename, &st) == 0) {
        header->dataChunkDataSize = st.st_size;
        header->riffChunkDataSize = header->dataChunkDataSize + sizeof(WAVHeader) - 8;
    } else {
        av_log(NULL, AV_LOG_INFO, "获取文件大小失败：%s\n", pcmFilename);
        return;
    }
    // 打开wav文件
    FILE *wavFile = fopen(wavFilename, "wb");
    if (wavFile == NULL) {
        av_log(NULL, AV_LOG_INFO, "文件打开失败：%s\n", wavFilename);
        return;
    }
    // 写入头部
    fwrite((const char *) header, 1, sizeof(*header), wavFile);
    // 写入pcm数据
    char buf[1024];
    int size;
    while ((size = (int) fread(buf, 1, sizeof(buf), pcmFile)) > 0) {
        fwrite(buf, 1, size, wavFile);
    }
    // 关闭文件
    fclose(pcmFile);
    fclose(wavFile);
}

int main(int argc, char *argv[]) {
    WAVHeader header = {
            .riffChunkId = {'R', 'I', 'F', 'F'},
            .format = {'W', 'A', 'V', 'E'},
            .fmtChunkId = {'f', 'm', 't', ' '},
            .fmtChunkDataSize = 16,
            .audioFormat = AUDIO_FORMAT_PCM,
            .dataChunkId = {'d', 'a', 't', 'a'}
    };
    header.numChannels = 2;
    header.sampleRate = 44100;
    header.bitsPerSample = 16;
    pcm2wav(&header, "C:/Users/xu/Desktop/output.pcm", "C:/Users/xu/Desktop/output.wav");
    return 0;
}